package suncertify.db;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 */
public class DataValidator {

    /**
     * Validates the record name field. A valid name field must satisfy these rules:
     * <ol>
     * <li>Must not be null.</li>
     * <li>The trimmed name length must be equal or smaller than {@link Data#FIELD_LENGTH_NAME}</li>. The name is
     * trimmed with {@link String#trim()}.
     * <li>The trimmed name value must begin with an alphanumeric character (0-9, a-z, A-Z) followed by zero or more
     * alphanumeric characters, a comma character (','), a space character or an ampersand character ('&').</li>
     * </ol>
     * 
     * @param name
     *            The name field value.
     * @return True if the above rules are satisfied, return false otherwise.
     */
    public static boolean isNameValid(String name) {

	if (name == null) {
	    return false;
	}

	String trimmedName = name.trim();

	if (trimmedName.length() > Data.FIELD_LENGTH_NAME) {
	    return false;
	}

	return isStringFieldValid(trimmedName);
    }

    /**
     * Validates the record location field. A valid location field must satisfy these rules:
     * <ol>
     * <li>Must not be null.</li>
     * <li>The trimmed location length must be equal or smaller than {@link Data#FIELD_LENGTH_LOCATION}</li>. The
     * location is trimmed with {@link String#trim()}.
     * <li>The trimmed location value must begin with an alphanumeric character (0-9, a-z, A-Z) followed by zero or more
     * alphanumeric characters, a comma character (','), a space character or an ampersand character ('&').</li>
     * </ol>
     * 
     * @param location
     *            The location field value.
     * @return True if the above rules are satisfied, return false otherwise.
     */
    public static boolean isLocationValid(String location) {

	if (location == null) {
	    return false;
	}

	String trimmedLocation = location.trim();

	if (trimmedLocation.length() > Data.FIELD_LENGTH_LOCATION) {
	    return false;
	}

	return isStringFieldValid(trimmedLocation);
    }

    /**
     * Validates the record specialties field. A valid specialties field must satisfy these rules:
     * <ol>
     * <li>Must not be null.</li>
     * <li>The trimmed specialties length must be equal or smaller than {@link Data#FIELD_LENGTH_SPECIALTIES}</li>. The
     * location is trimmed with {@link String#trim()}.
     * <li>The trimmed specialties value must begin with an alphanumeric character (0-9, a-z, A-Z) followed by zero or
     * more alphanumeric characters, a comma character (','), a space character or an ampersand character ('&').</li>
     * </ol>
     * 
     * @param specialties
     *            The specialties field value.
     * @return True if the above rules are satisfied, return false otherwise.
     */
    public static boolean isSpecialtiesValid(String specialties) {

	if (specialties == null) {
	    return false;
	}

	String trimmedSpecialties = specialties.trim();

	if (trimmedSpecialties.length() > Data.FIELD_LENGTH_SPECIALTIES) {
	    return false;
	}

	return isStringFieldValid(trimmedSpecialties);
    }

    /**
     * Validates the record size field. A valid size field must satisfy these rules:
     * <ol>
     * <li>Must not be null.</li>
     * <li>The size string must represent a positive integer between "100000" and "999999".</li>
     * <li>The number of characters must not be larger than {@link Data#FIELD_LENGTH_SIZE}.</li>
     * </ol>
     * 
     * @param size
     *            The size field value.
     * @return True if the above rules are satisfied, return false otherwise.
     */
    public static boolean isSizeValid(String size) {

	if (size == null) {
	    return false;
	}

	String expression = "^[1-9]{1,1}[0-9]{0,5}$";
	Pattern pattern = Pattern.compile(expression);
	Matcher matcher = pattern.matcher(size.trim());

	return matcher.find();
    }

    /**
     * Validates the record owner field. A valid owner field must satisfy these rules:
     * <ol>
     * <li>Must not be null.</li>
     * <li>The owner string must represent a positive integer between "10000000" and "99999999".</li>
     * <li>The number of characters must not be larger than {@link Data#FIELD_LENGTH_OWNER}.</li>
     * </ol>
     * 
     * @param owner
     *            The owner field value.
     * @return True if the above rules are satisfied, return false otherwise.
     */
    public static boolean isOwnerValid(String owner) {

	if (owner == null) {
	    return false;
	}

	String expression = "^[1-9]{1,1}[0-9]{7,7}$";
	Pattern pattern = Pattern.compile(expression);
	Matcher matcher = pattern.matcher(owner.trim());

	return matcher.find();
    }

    /**
     * Validates the record rate field. A valid rate field must satisfy these rules:
     * <ol>
     * <li>Must not be null.</li>
     * <li>Must start with the US currency symbol '$'.</li>
     * <li>Followed by a numeric character between 1 and 9.</li>
     * <li>Followed by 0 to 3 numeric characters between 0 and 9.
     * <li>Followed by the US decimal point character '.'</li>
     * <li>Followed by one numeric character between 1 and 9.</li>
     * <li>Followed by one numeric character between 0 and 9.</li>
     * </ol>
     * 
     * <p>
     * Examples of valid rate strings are: "$50.00", "$9999.99", "$100.50" and "$9.20"
     * 
     * <p>
     * Examples of not valid rate strings are: "50.00", "$9,999.99", "$010.50" and "$9.05"
     * 
     * @param rate
     *            The rate field value.
     * @return True if the above rules are satisfied, return false otherwise.
     */
    public static boolean isRateValid(String rate) {

	// check if rate is null
	if (rate == null) {
	    return false;
	}

	// This regular expression represent the rules in the function description.
	Pattern pattern = Pattern.compile("^\\$[1-9]{1,1}[0-9]{0,3}\\.[0-9]{2,2}$");
	Matcher matcher = pattern.matcher(rate.trim());

	return matcher.find();
    }

    /**
     * Returns true if the <code>fieldValue</code> obeys to these rules:
     * <ol>
     * <li>The first character is an alphanumeric character (0-9) or (a-z) or (A-Z).</li>
     * <li>Followed by 0 or more alphanumeric characters, a comma ',' character, an ampersand character '&' or a space
     * character.</li>
     * </ol>
     * 
     * @param fieldValue
     *            The value to be investigated.
     * @return True if the above rules are obeyed, return false otherwise.
     */
    private static boolean isStringFieldValid(String fieldValue) {

	Pattern pattern = Pattern.compile("^[0-9a-zA-Z]{1,1}[0-9a-zA-Z\\,\\& ]*$");
	Matcher matcher = pattern.matcher(fieldValue);

	return matcher.find();
    }
}
